#include "PageCache.h"

// 分配Span逻辑（改造后）
Span* PageCache::NewSpan(size_t k) {
    assert(k < NPAGES);
    //std::lock_guard<std::mutex> lock(_mutex);

    // 查找合适的Span
    for (size_t i = k; i < NPAGES; ++i) {
        if (!_spanLists[i].Empty()) {
            Span* s = _spanLists[i].PopFront();
            size_t n_k;
            // 切割Span
            if (i > k) {
                n_k= i - k;
                Span* seps = _spanPool.New();
                
                // 剩余页的Span设置
                seps->_pageId = s->_pageId + k;
                seps->_n = n_k;
                seps->_freeList = (char*)s->_freeList + k * PAGESIZE;
                seps->_isUse = false;
                PAGE_ID sz=seps->_pageId;
                // 确保剩余页路径存在并映射
                //if (_pageMap.Ensure(sz, n_k)) {
                    _pageMap.set(seps->_pageId, seps);
                    _pageMap.set(seps->_pageId + n_k - 1, seps);
                    _spanLists[n_k].PushFront(seps);
                //}
               
            }
            
            // 设置当前Span
            s->_n = k;
            s->_isUse = true;
            
            // 确保分配页路径存在并映射
            // if (!_pageMap.Ensure(s->_pageId, k)) {
            //     // 回滚切割
            //     if (i > k) {
            //         Span* seps = _spanLists[n_k].PopFront();
            //         _spanPool.Delete(seps);
            //     }
            //     _spanLists[i].PushFront(s);
            //     return nullptr;
            // }
            for (size_t i = 0; i < k; ++i) {
                _pageMap.set(s->_pageId + i, s);
            }
            return s;
        }
    }

    // 向系统申请内存
    void* ptr = SystemAlloc(128);  // 申请128页
    if (!ptr) return nullptr;
    
    Span* s = _spanPool.New();
    s->_pageId = (PAGE_ID)ptr >> SHIFTPAGE;
    s->_n = 128;
    s->_freeList = ptr;
    s->_isUse = false;
    _spanLists[128].PushFront(s);
    
    // 递归分配
    return NewSpan(k);
}

// 对象到Span的映射
Span* PageCache::MapObjectToSpan(void* obj) {
    //std::lock_guard<std::mutex> lock(_mutex);
    uintptr_t page = (uintptr_t)obj >> SHIFTPAGE;
    return static_cast<Span*>(_pageMap.get(page));
}

// 释放并合并Span
//合并超过128页后就不应该进行合并
void PageCache::ReleaseSpanToPageCache(Span* s) {
    assert(s);
    //对于大于128页的内存直接调用系统释放
	if (s->_n > NPAGES-1)
	{
		void* ptr = (void*)(s->_pageId << PAGE_SHIFT);
		SystemFree(ptr,s->_n);
		//delete span;
		_spanPool.Delete(s);

		return;
	}

    //std::lock_guard<std::mutex> lock(_mutex);
    uintptr_t pageId = s->_pageId;

    // 向前合并
    while (true) {
        //printf("在向前合并\n");
        Span* prevs = static_cast<Span*>(_pageMap.get(pageId - 1));
        if (!prevs || prevs->_isUse) break;
		//超过128页，不合并
        if (prevs->_n + s->_n > NPAGES-1)
		{
			break;
		}
        // 合并逻辑
        _spanLists[prevs->_n].Erase(prevs);
        prevs->_n += s->_n;
        _spanPool.Delete(s);
        s = prevs;
        pageId = s->_pageId;
    }

    // 向后合并
    while (true) {
        //printf("在向后合并\n");
        Span* nexts = static_cast<Span*>(_pageMap.get(s->_pageId + s->_n));
        if (!nexts || nexts->_isUse) break;
		//超过128页，不合并
        if (nexts->_n + s->_n > NPAGES-1)
		{
			break;
		}
        _spanLists[nexts->_n].Erase(nexts);
        s->_n += nexts->_n;
        _spanPool.Delete(nexts);
    }

    // 重新映射合并后的Span
    // if (!_pageMap.Ensure(s->_pageId, s->_n)) {
    //     assert(false); // 合并后路径应存在
    // }
    _pageMap.set(s->_pageId, s);
    _pageMap.set(s->_pageId + s->_n - 1, s);
	//printf("页数：%d\n",s->_n);
    _spanLists[s->_n].PushFront(s);
    s->_isUse = false;
}

// 插入页到Span
void PageCache::InsertPageToSpan(void* obj, size_t kpage) {
    //std::lock_guard<std::mutex> lock(_mutex);
    Span* s = _spanPool.New();
    s->_pageId = (uintptr_t)obj >> SHIFTPAGE;
    s->_n = kpage;
    s->_objSize = kpage * PAGESIZE;
    s->_isUse = true;
    
    // if (!_pageMap.Ensure(s->_pageId, kpage)) {
    //     _spanPool.Delete(s);
    //     return;
    // }
    _pageMap.set(s->_pageId, s);
}

PageCache PageCache::_sInst;  